HAL SAI initialization and configuration functions migration ¶
The goal of this page is to show how to migrate the Init sequence using STM32CubeMX2:
Open STM32CubeMX2 SAI configuration panel
Configure the SAI main features
Configure the advanced SAI features.
Configure the SAI GPIO PINS
Configure the SAI DMA(s) if the application requires to use the SAI in DMA mode.
Configure the NVIC if the application requires the SAI to be used in IT mode.
Generate the code
HAL SAI configuration panel ¶
Create a new project with the STM32CubeMX2, then start the initialization and the main configuration.
HAL SAI main features configuration ¶
Configure the SAI main features.
HAL SAI advanced features configuration ¶
Configure the advanced SAI features.
GPIO configuration ¶
Configure the
SAI1_MCLK_A,
SAI1_SD_A,
SAI1_SCK_A,
SAI1_FS_A,
SAI1_D1,
SAI1_D2,
SAI1_D3,
SAI1_CK1
and
SAI1_CK2
pins.
DMA configuration ¶
Configure the DMA RX channel when the Audio mode is Master Receiver or Slave Receiver, and configure the DMA TX channel when the Audio mode is Master Transmitter or Slave Transmitter.
NVIC configuration ¶
Configure the NVIC in case of an interrupt.
Generated SAI initialization and de-initialization sequences ¶
The SAI initialization sequence is generated in the
mx_sai1_a_init
and
mx_sai1_b_init
functions in
mx_sai1.c
file under
$YOUR_PROJECT_NAME$/$YOUR_PROJECT_NAME$_SW/generated/STM32Cube_CodeGen.
Note
In HAL2, the PDM parameters is only available for SAI1 block A and is supported in master receiver mode.
As the hardware may vary, this will naturally have an impact on the RCC clock, pin and NVIC interrupt line used by the application.
|
Topic |
HAL1 code snippet |
HAL2 code snippet |
|---|---|---|
|
Declaration of the handle |
GPIO_InitTypeDef GPIO_InitStruct;
SAI_HandleTypeDef hsai_BlockA1;
SAI_HandleTypeDef hsai_BlockB1;
|
hal_gpio_config_t gpio_config;
hal_sai_config_t sai_config;
hal_sai_pdm_mic_delay_t pdm_mic_delay;
hal_sai_handle_t hSAI1_A;
hal_sai_handle_t hSAI1_B;
|
|
Initialization and configuration sequence |
static void MX_SAI1_Init(void)
{
hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_RX;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_8K;
hsai_BlockA1.Init.DataSize = SAI_DATASIZE_8;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
hsai_BlockA1.FrameInit.FrameLength = 8;
hsai_BlockA1.FrameInit.ActiveFrameLength = 1;
hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;
hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 1;
hsai_BlockA1.SlotInit.SlotActive = 0x00000000;
hsai_BlockA1.Init.Synchro = SAI_SYNCHRONOUS;
hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_ENABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
hsai_BlockA1.Init.PdmInit.Activation = DISABLE;
hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;
hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)
{
Error_Handler();
}
hsai_BlockB1.Instance = SAI1_Block_B;
hsai_BlockB1.Init.AudioMode = SAI_MODEMASTER_TX;
hsai_BlockB1.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockB1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockB1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockB1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;
hsai_BlockB1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_192K;
hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockB1.Init.MckOutput = SAI_MCK_OUTPUT_DISABLE;
hsai_BlockB1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB1,
SAI_I2S_STANDARD,
SAI_PROTOCOL_DATASIZE_16BIT,
2) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)
{
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
uint32_t SAI1_client =0;
/* SAI1 */
if(hsai->Instance==SAI1_Block_A)
{
/* Peripheral clock enable */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
if (SAI1_client == 0)
{
__HAL_RCC_SAI1_CLK_ENABLE();
}
SAI1_client ++;
/**SAI1_A_Block_A GPIO Configuration
PD6 ------> SAI1_SD_A
PE4 ------> SAI1_FS_A
PE5 ------> SAI1_SCK_A
*/
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
if(hsai->Instance==SAI1_Block_B)
{
/* Peripheral clock enable */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
if (SAI1_client == 0)
{
__HAL_RCC_SAI1_CLK_ENABLE();
}
SAI1_client ++;
/**SAI1_B_Block_B GPIO Configuration
PB5 ------> SAI1_SD_B
PF8 ------> SAI1_SCK_B
PF7 ------> SAI1_MCLK_B
PF9 ------> SAI1_FS_B
*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF13_SAI1;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
}
}
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
}
|
hal_sai_handle_t *mx_sai1_a_init(void)
{
if (HAL_SAI_Init(&hSAI1_A, HAL_SAI1_A) != HAL_OK)
{
return NULL;
}
HAL_RCC_SAI1_EnableClock();
if (HAL_RCC_SAI1_SetKernelClkSource(HAL_RCC_SAI1_CLK_SRC_PLL1R) != HAL_OK)
{
return NULL;
}
sai_config.protocol = HAL_SAI_PROTOCOL_FREE;
sai_config.mode = HAL_SAI_MODE_MASTER_RX;
sai_config.audio_frequency = HAL_SAI_AUDIO_FREQUENCY_8KHZ;
sai_config.mclk_oversampling = HAL_SAI_MCLK_OVERSAMPLING_DISABLE;
sai_config.data_size = HAL_SAI_DATA_SIZE_8BITS;
sai_config.bit_order = HAL_SAI_BIT_ORDER_MSB;
sai_config.clock_strobing_edge = HAL_SAI_CLOCK_STROBING_FALLING_EDGE;
sai_config.frame.frame_length = 8;
sai_config.frame.active_frame_length = 1;
sai_config.frame.fs_definition = HAL_SAI_FS_START_FRAME;
sai_config.frame.fs_polarity = HAL_SAI_FS_POLARITY_FALLING;
sai_config.frame.fs_offset = HAL_SAI_FS_FIRST_BIT;
sai_config.slot.slot_first_bit_offset = 0;
sai_config.slot.slot_size = HAL_SAI_SLOT_SIZE_DATA_SIZE;
sai_config.slot.slot_number = 1;
sai_config.slot.slot_active = HAL_SAI_SLOT_ACTIVE_0;
if (HAL_SAI_SetConfig(&hSAI1_A, &sai_config) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_SetSyncOutput(&hSAI1_A,
HAL_SAI_SYNC_OUTPUT_BLOCK_A_ENABLE) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_SetCompanding(&hSAI1_A,
HAL_SAI_COMPANDING_ALAW_2CPL) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_SetFifoThreshold(&hSAI1_A,
HAL_SAI_FIFO_THRESHOLD_FULL) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_EnableMclkOutput(&hSAI1_A) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_EnableOutputDrive(&hSAI1_A) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_EnableTristateSDOutput(&hSAI1_A) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_EnableMonoMode(&hSAI1_A) != HAL_OK)
{
return NULL;
}
if (HAL_SAI_EnablePdm(&hSAI1_A,
3,
HAL_SAI_PDM_CLOCK1_CLOCK2_ENABLE) != HAL_OK)
{
return NULL;
}
pdm_mic_delay.pdm_mic_pairs_nbr = 3;
pdm_mic_delay.pdm_left_delay = 0;
pdm_mic_delay.pdm_right_delay = 0;
if (HAL_SAI_SetPdmMicDelay(&hSAI1_A,
&pdm_mic_delay) != HAL_OK)
{
return NULL;
}
HAL_RCC_GPIOB_EnableClock();
HAL_RCC_GPIOD_EnableClock();
HAL_RCC_GPIOE_EnableClock();
HAL_RCC_GPIOA_EnableClock();
/** SAI1_A GPIO Configuration
PB2 ------> SAI1_SD_A
PE4 ------> SAI1_FS_A
PD6 ------> SAI1_SCK_A
*/
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.alternate = HAL_GPIO_AF_6;
HAL_GPIO_Init(HAL_GPIOB, HAL_GPIO_PIN_2, &gpio_config);
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.alternate = HAL_GPIO_AF_6;
HAL_GPIO_Init(HAL_GPIOD, HAL_GPIO_PIN_6, &gpio_config);
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.alternate = HAL_GPIO_AF_6;
HAL_GPIO_Init(HAL_GPIOE, HAL_GPIO_PIN_4 , &gpio_config);
return &hSAI1_A;
}
hal_sai_handle_t *mx_sai1_a_gethandle(void)
{
return &hSAI1_A;
}
hal_sai_handle_t *mx_sai1_b_init(void)
{
hal_sai_config_t sai_config;
if (HAL_SAI_Init(&hSAI1_B, HAL_SAI1_B) != HAL_OK)
{
return NULL;
}
HAL_RCC_SAI1_EnableClock();
if (HAL_RCC_SAI1_SetKernelClkSource(HAL_RCC_SAI1_CLK_SRC_PLL1R) != HAL_OK)
{
return NULL;
}
sai_config.mode = HAL_SAI_MODE_MASTER_TX;
sai_config.audio_frequency = HAL_SAI_AUDIO_FREQUENCY_8KHZ;
sai_config.mclk_oversampling = HAL_SAI_MCLK_OVERSAMPLING_DISABLE;
sai_config.protocol = HAL_SAI_PROTOCOL_FREE;
sai_config.data_size = HAL_SAI_DATA_SIZE_8BITS;
sai_config.bit_order = HAL_SAI_BIT_ORDER_MSB;
sai_config.clock_strobing_edge = HAL_SAI_CLOCK_STROBING_FALLING_EDGE;
sai_config.slot.slot_first_bit_offset = 0;
sai_config.slot.slot_size = HAL_SAI_SLOT_SIZE_DATA_SIZE;
sai_config.slot.slot_number = 2;
sai_config.slot.slot_active = (HAL_SAI_SLOT_ACTIVE_0);
sai_config.frame.frame_length = 16;
sai_config.frame.active_frame_length = 8;
sai_config.frame.fs_definition = HAL_SAI_FS_START_FRAME;
sai_config.frame.fs_polarity = HAL_SAI_FS_POLARITY_FALLING;
sai_config.frame.fs_offset = HAL_SAI_FS_FIRST_BIT;
if (HAL_SAI_SetConfig(&hSAI1_B, &sai_config) != HAL_OK)
{
return NULL;
}
HAL_RCC_GPIOE_EnableClock();
HAL_RCC_GPIOA_EnableClock();
/** SAI1_B GPIO Configuration
PE3 ------> SAI1_SD_B
PA8 ------> SAI1_SCK_B
PA7 ------> SAI1_FS_B
*/
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.alternate = HAL_GPIO_AF_6;
HAL_GPIO_Init(HAL_GPIOE, HAL_GPIO_PIN_3, &gpio_config);
gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
gpio_config.pull = HAL_GPIO_PULL_UP;
gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
gpio_config.alternate = HAL_GPIO_AF_6;
HAL_GPIO_Init(HAL_GPIOA, HAL_GPIO_PIN_8 | HAL_GPIO_PIN_7, &gpio_config);
return &hSAI1_B;
}
hal_sai_handle_t *mx_sai1_b_gethandle(void)
{
return &hSAI1_B;
}
|
|
Deinitialization sequence |
void HAL_SAI_MspDeInit(SAI_HandleTypeDef* hsai)
{
/* SAI1 */
if(hsai->Instance==SAI1_Block_A)
{
SAI1_client --;
if (SAI1_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI1_CLK_DISABLE();
}
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_6);
HAL_GPIO_DeInit(GPIOE, GPIO_PIN_4|GPIO_PIN_5);
}
if(hsai->Instance==SAI1_Block_B)
{
SAI1_client --;
if (SAI1_client == 0)
{
/* Peripheral clock disable */
__HAL_RCC_SAI1_CLK_DISABLE();
}
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_5);
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_9);
}
}
|
void mx_sai1_a_deinit(void)
{
(void)HAL_SAI_DeInit(&hSAI1_A);
HAL_RCC_SAI1_Reset();
HAL_RCC_SAI1_DisableClock();
/* De-initialize all GPIO pins associated with SAI1 */
HAL_GPIO_DeInit(HAL_GPIOB, HAL_GPIO_PIN_2);
HAL_GPIO_DeInit(HAL_GPIOD, HAL_GPIO_PIN_6);
HAL_GPIO_DeInit(HAL_GPIOE, HAL_GPIO_PIN_4);
}
void mx_sai1_b_deinit(void)
{
(void)HAL_SAI_DeInit(&hSAI1_B);
HAL_RCC_SAI1_Reset();
HAL_RCC_SAI1_DisableClock();
/* De-initialize all GPIO pins associated with SAI1 */
HAL_GPIO_DeInit(HAL_GPIOE, HAL_GPIO_PIN_3);
HAL_GPIO_DeInit(HAL_GPIOA, HAL_GPIO_PIN_7 | HAL_GPIO_PIN_8);
}
|